wayland: add gdk_event_is_scroll_stop_event()
authorPeter Hutterer <peter.hutterer@who-t.net>
Wed, 21 Oct 2015 00:14:40 +0000 (10:14 +1000)
committerCarlos Garnacho <carlosg@gnome.org>
Mon, 18 Jan 2016 20:36:23 +0000 (21:36 +0100)
And use it to handle kinetic scrolling in the GtkScrolledWindow.

However, dropping the delta check causes the X11-based kinetic
scroll to break since we don't have the stop event here. Correct handling of
xf86-input-libinput-based scroll events is still being discussed.

https://bugzilla.gnome.org/show_bug.cgi?id=756729

docs/reference/gdk/gdk3-sections.txt
gdk/gdkevents.c
gdk/gdkevents.h
gdk/gdkwindow.c
gdk/wayland/gdkdevice-wayland.c
gtk/gtkscrolledwindow.c

index 7b1b9f7419c5478735ae2a114d85e746067348d8..cfcce263ecadc1867dc13f8b4232c60e66fbc277 100644 (file)
@@ -859,6 +859,7 @@ gdk_event_get_keyval
 gdk_event_get_root_coords
 gdk_event_get_scroll_direction
 gdk_event_get_scroll_deltas
+gdk_event_is_scroll_stop_event
 gdk_event_get_state
 gdk_event_get_time
 gdk_event_get_window
index 9ed43176aa225356bfcfd4160856bdbbf4dc1ae1..83f8ab11f2efaae013c71fbf57ba630318a7815b 100644 (file)
@@ -562,6 +562,7 @@ gdk_event_new (GdkEventType type)
       new_event->scroll.y_root = 0.;
       new_event->scroll.delta_x = 0.;
       new_event->scroll.delta_y = 0.;
+      new_event->scroll.is_stop = FALSE;
       break;
     case GDK_ENTER_NOTIFY:
     case GDK_LEAVE_NOTIFY:
@@ -1418,6 +1419,28 @@ gdk_event_get_scroll_deltas (const GdkEvent *event,
   return fetched;
 }
 
+/**
+ * gdk_event_is_scroll_stop_event
+ * @event: a #GdkEvent
+ *
+ * Check whether a scroll event is a stop scroll event. Scroll sequences
+ * with smooth scroll information may provide a stop scroll event once the
+ * interaction with the device finishes, e.g. by lifting a finger. This
+ * stop scroll event is the signal that a widget may trigger kinetic
+ * scrolling based on the current velocity.
+ *
+ * Stop scroll events always have a a delta of 0/0.
+ *
+ * Returns: %TRUE if the event is a scroll stop event
+ *
+ * Since: 3.20
+ */
+gboolean
+gdk_event_is_scroll_stop_event (const GdkEvent *event)
+{
+  return event->scroll.is_stop;
+}
+
 /**
  * gdk_event_get_axis:
  * @event: a #GdkEvent
index ca019b7b9dfdbc072a907481fe8dc8fa7933c616..a502b2743fbc52b144f250ff1f6cba1350e2da3e 100644 (file)
@@ -824,6 +824,7 @@ struct _GdkEventScroll
   gdouble x_root, y_root;
   gdouble delta_x;
   gdouble delta_y;
+  guint is_stop : 1;
 };
 
 /**
@@ -1377,6 +1378,9 @@ gboolean  gdk_event_get_scroll_deltas   (const GdkEvent *event,
                                          gdouble         *delta_x,
                                          gdouble         *delta_y);
 
+GDK_AVAILABLE_IN_3_20
+gboolean  gdk_event_is_scroll_stop_event (const GdkEvent *event);
+
 GDK_AVAILABLE_IN_ALL
 gboolean  gdk_event_get_axis            (const GdkEvent  *event,
                                          GdkAxisUse       axis_use,
index 57ffa641e15d3e46928b68a63c9c778d933bc0bd..6995db9eef9fa472e0ad17a48f802d025e75f544 100644 (file)
@@ -9328,6 +9328,7 @@ proxy_button_event (GdkEvent *source_event,
       event->scroll.device = source_event->scroll.device;
       event->scroll.delta_x = source_event->scroll.delta_x;
       event->scroll.delta_y = source_event->scroll.delta_y;
+      event->scroll.is_stop = source_event->scroll.is_stop;
       gdk_event_set_source_device (event, source_device);
       return TRUE;
 
index 50d07bd7f466ab56ad3c7ba6c22c416b48605cb5..1afb9b001d954dd05c8becc6af5d3ee8b3e3d77c 100644 (file)
@@ -62,6 +62,7 @@ struct _GdkWaylandPointerFrameData
   /* Specific to the scroll event */
   gdouble delta_x, delta_y;
   int32_t discrete_x, discrete_y;
+  gint8 is_scroll_stop;
 };
 
 struct _GdkWaylandSeat
@@ -972,7 +973,8 @@ flush_discrete_scroll_event (GdkWaylandSeat     *seat,
 static void
 flush_smooth_scroll_event (GdkWaylandSeat *seat,
                            gdouble         delta_x,
-                           gdouble         delta_y)
+                           gdouble         delta_y,
+                           gboolean        is_stop)
 {
   GdkEvent *event;
 
@@ -980,6 +982,7 @@ flush_smooth_scroll_event (GdkWaylandSeat *seat,
   event->scroll.direction = GDK_SCROLL_SMOOTH;
   event->scroll.delta_x = delta_x;
   event->scroll.delta_y = delta_y;
+  event->scroll.is_stop = is_stop;
 
   _gdk_wayland_display_deliver_event (seat->display, event);
 }
@@ -988,6 +991,8 @@ static void
 flush_scroll_event (GdkWaylandSeat             *seat,
                     GdkWaylandPointerFrameData *pointer_frame)
 {
+  gboolean is_stop = FALSE;
+
   if (pointer_frame->discrete_x || pointer_frame->discrete_y)
     {
       GdkScrollDirection direction;
@@ -1004,14 +1009,24 @@ flush_scroll_event (GdkWaylandSeat             *seat,
       flush_discrete_scroll_event (seat, direction);
     }
 
+  /* Axes can stop independently, if we stop on one axis but have a
+   * delta on the other, we don't count it as a stop event.
+   */
+  if (pointer_frame->is_scroll_stop &&
+      pointer_frame->delta_x == 0 &&
+      pointer_frame->delta_y == 0)
+    is_stop = TRUE;
+
   flush_smooth_scroll_event (seat,
                              pointer_frame->delta_x,
-                             pointer_frame->delta_y);
+                             pointer_frame->delta_y,
+                             is_stop);
 
   pointer_frame->delta_x = 0;
   pointer_frame->delta_y = 0;
   pointer_frame->discrete_x = 0;
   pointer_frame->discrete_y = 0;
+  pointer_frame->is_scroll_stop = FALSE;
 }
 
 static void
@@ -1369,6 +1384,8 @@ pointer_handle_axis_stop (void              *data,
       g_return_if_reached ();
     }
 
+  pointer_frame->is_scroll_stop = TRUE;
+
   GDK_NOTE (EVENTS,
             g_message ("axis stop, seat %p", seat));
 }
index b27028cc4449fd2e861d82bbc560db31bfbbffc6..0df1a6213458adb81bed19f504af5e71bf5638cc 100644 (file)
@@ -3321,7 +3321,7 @@ gtk_scrolled_window_scroll_event (GtkWidget      *widget,
        * after scrolling finished, start kinetic scrolling when this
        * happens.
        */
-      if (delta_y == 0 && delta_x == 0)
+      if (gdk_event_is_scroll_stop_event ((GdkEvent *) event))
         {
           handled = TRUE;
           start_deceleration = TRUE;